home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 220 / 220.xpi / chrome / flashgot.jar / content / flashgot / HttpInterceptor.js < prev    next >
Encoding:
JavaScript  |  2010-01-24  |  7.5 KB  |  230 lines

  1. /***** BEGIN LICENSE BLOCK *****
  2.  
  3.     FlashGot - a Firefox extension for external download managers integration
  4.     Copyright (C) 2004-2009 Giorgio Maone - g.maone@informaction.com
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.                              
  20. ***** END LICENSE BLOCK *****/
  21.  
  22. function HttpInterceptor() {
  23.   CC["@mozilla.org/uriloader;1"].getService(
  24.     CI.nsIURILoader).registerContentListener(this);
  25. }
  26.  
  27. HttpInterceptor.prototype = {
  28.   
  29.   autoStart: false,
  30.   interceptAll: true,
  31.   bypassAutoStart: false,
  32.   forceAutoStart: false,
  33.   
  34.   lastPost: null, // last uploadChannel
  35.    
  36.   QueryInterface: xpcom_generateQI([
  37.     CI.nsIURIContentListener,
  38.     CI.nsIObserver, 
  39.     CI.nsISupportsWeakReference,
  40.     CI.nsISupports
  41.   ]),
  42.   
  43.   
  44.   setup: function() { // profile initialization
  45.     this.autoStart = fg.getPref("autoStart", false);
  46.     this.interceptAll = fg.getPref("interceptAll", true);
  47.   },
  48.   
  49.   dispose: function() {
  50.     CC["@mozilla.org/uriloader;1"].getService(
  51.         CI.nsIURILoader).unRegisterContentListener(this);
  52.   },
  53.   
  54.   log: function(msg) {
  55.     fg.log(msg);
  56.   },
  57.   
  58.   _shouldIntercept: function(contentType) {
  59.     // dump("FG: _shouldIntercept("+contentType+")\n");
  60.     if (this.bypassAutoStart) return false;
  61.     
  62.     if (!(fg.DMS && fg.DMS.found)) return false;
  63.     if (this.forceAutoStart) return true;
  64.     
  65.     if (!this.autoStart) return false;
  66.     
  67.     if (this.interceptAll &&
  68.       !/\bxpinstall|text|xml|vnd\.mozilla|multipart\/x-mixed-replace\b/.test(contentType)) {
  69.       return true;
  70.     }
  71.  
  72.     if (contentType == "application/x-unknown-content-type" || /\b(?:xml|rss|javascript|json)\b/.test(contentType)) return false;
  73.     var ms = MediaSniffer.mimeService;
  74.     return fg.extensions.some(function(e) {
  75.       try { return contentType == ms.getTypeFromExtensions(e); } catch(ex) { return false; }
  76.     });
  77.   }
  78.   _willHandle: function(url, contentType) {
  79.     if (!/^(http|https|ftp|sftp|rtsp|mms):/i.test(url) ) {
  80.       if ((/^\s*javascript/i).test(url)) this.log("JavaScript url intercepted: "+url);
  81.       return false;
  82.     }
  83.     return true;
  84.   }
  85. ,
  86.   extractPostData: function(channel, res) {
  87.     res = res || {};
  88.     res.postData = res.postStream = null;
  89.     if (channel instanceof CI.nsIUploadChannel &&
  90.        channel.uploadStream instanceof CI.nsISeekableStream) {
  91.       this.log("Extracting post data...");
  92.       var sis;
  93.       try {
  94.         res.postStream = channel.uploadStream;
  95.         res.postStream.seek(0, 0);
  96.         sis = CC['@mozilla.org/scriptableinputstream;1'].createInstance(CI.nsIScriptableInputStream);
  97.         sis.init(res.postStream);
  98.         var postData  = sis.read(sis.available());
  99.         res.postStream.seek(0, 0);
  100.         
  101.         // buffered persistent copy 
  102.         res.postStream = CC["@mozilla.org/io/string-input-stream;1"].createInstance(CI.nsIStringInputStream);
  103.         res.postStream.setData(postData, postData.length);
  104.         if (res.postStream instanceof CI.nsISeekableStream) res.postStream.seek(0, 0);
  105.         
  106.         // remove headers
  107.         postData = postData.replace(/\s+$/,'').split(/[\r\n]+/)
  108.         res.postData = postData[postData.length - 1];
  109.       } catch(ex) {
  110.         this.log(ex.message);
  111.       } finally {
  112.         if (sis) sis.close();
  113.       }
  114.     }
  115.     return res;
  116.   },
  117.   /* nsIURIContentListener */
  118.   
  119.   canHandleContent: function(contentType, isContentPreferred, desiredContentType) {
  120.     // dump("FG: canHandleContent "+contentType+")\n");
  121.     return this._shouldIntercept(contentType);
  122.   }
  123. ,
  124.   lastRequest: null,
  125.   doContent: function(contentType, isContentPreferred, channel, contentHandler) {
  126.  
  127.     channel.QueryInterface(CI.nsIChannel);
  128.     const uri = channel.URI;
  129.     // dump("FG: doContent " +contentType + " " + uri.spec + "\n");
  130.     if (!this._willHandle(uri.spec, contentType)) {
  131.       throw new Error("FlashGot not interested in " + contentType + " from " + uri.spec);
  132.     }
  133.     
  134.     this.log("Intercepting download...");
  135.  
  136.     const pathParts=uri.path.split(/\//);
  137.     var links = [ {
  138.      href: channel.URI.spec, 
  139.      description: pathParts[pathParts.length-1],
  140.      noRedir: true
  141.     } ];
  142.     
  143.     
  144.     
  145.     if (channel instanceof CI.nsIHttpChannel) {
  146.       links.referrer = channel.referrer && channel.referrer.spec || "";
  147.       this.extractPostData(channel, links);
  148.     }
  149.     
  150.     try {
  151.         links.document = channel.notificationCallbacks.QueryInterface(
  152.             CI.nsIInterfaceRequestor).getInterface(
  153.             CI.nsIDOMWindow).document;
  154.         links.browserWindow = DOM.getChromeWindow(links.document.defaultView.top);
  155.         if (links.browserWindow.wrappedJSObject) links.browserWindow = links.browserWindow.wrappedJSObject;
  156.       } catch(e) {
  157.         this.log("Can't set referrer document for " + links[0].href + " from " + links.referrer);
  158.     }
  159.     
  160.     var firstAttempt;
  161.     if (contentHandler) {
  162.       this.lastRequest = null;
  163.       firstAttempt = true;
  164.       this.forceAutoStart = false;
  165.     } else {
  166.       var requestLines = [ channel.requestMethod, links[0].href, links.referrer || "", links.postData || ""].join("\n\n");
  167.       firstAttempt = this.lastRequest != requestLines;
  168.       this.lastRequest = requestLines;
  169.     }
  170.     
  171.     if (firstAttempt) {
  172.        var self = this;
  173.        fg.delayExec(function() {
  174.           self.forceAutoStart = false;
  175.           if(fg.download(links))
  176.             self.log("...interception done!");
  177.         }, 10);
  178.     } else {
  179.       // dump("Second attempt, skipping.\n");
  180.       this.lastRequest = null;
  181.       this.forceAutoStart = false;
  182.     }
  183.     
  184.     if (!channel.isPending()) { 
  185.       try {
  186.         channel.requestMethod = "HEAD";
  187.         channel.loadFlags = CI.nsIChannel.LOAD_RETARGETED | CI.nsIChannel.LOAD_RETARGETED_DOCUMENT_URI | CI.nsICachingChannel.LOAD_ONLY_FROM_CACHE;
  188.       } catch(e) {}
  189.     }
  190.     channel.cancel(NS_BINDING_ABORTED); 
  191.  
  192.     this.log("Original request cancelled.");
  193.     
  194.     return true;
  195.   },
  196.   contentHandler: {
  197.       onStartRequest: function(request, context) { 
  198.         throw "cancelled"; 
  199.       }, 
  200.       onStopRequest: function() {}, 
  201.       onDataAvailable: function() {}
  202.    }
  203. ,
  204.   isPreferred: function(contentType, desiredContentType) {
  205.     // dump("FG: isPreferred("+contentType+","+desiredContentType+")\n");
  206.     return this._shouldIntercept(contentType);
  207.   }
  208. ,
  209.   onStartURIOpen: function(uri) {
  210.     // dump("FG: onStartURIOpen "+ uri + (uri && uri.spec) + "\n");
  211.     return false;
  212.   }
  213. ,
  214.   // http-on-modify-request Observer 
  215.   observe: function(channel, topic, data) {
  216.     if (channel instanceof CI.nsIHttpChannel) {
  217.       
  218.       if (channel instanceof CI.nsIUploadChannel) {
  219.         this.lastPost = channel;
  220.       }
  221.       if (this.forceAutoStart) {
  222.         this.doContent("flashgot/forced", true, channel, null);
  223.         return;
  224.       }
  225.       
  226.       
  227.     }
  228.   }
  229. };